package org.cvcsc.weproject.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;

import org.cvcsc.weproject.controller.dto.RequestDtoTuneAttendanceItem;
import org.cvcsc.weproject.controller.dto.ResponseDtoAttendance;
import org.cvcsc.weproject.controller.dto.ResponseDtoAttendanceWithDetails;
import org.cvcsc.weproject.domain.*;
import org.cvcsc.weproject.repository.Finder;
import org.cvcsc.weproject.repository.ModelFinder;
import org.cvcsc.weproject.service.AttendanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/attendance")
public class AttendanceController {
    @Autowired
    private AttendanceService attendanceService;
    @Autowired
    private Finder<CourseSchedule, Long> courseScheduleRepository;
    @Autowired
    private Finder<Student, Long> studentRepository;

    @Autowired
    private ModelFinder modelFinder;

    private Finder<Attendance, Long> attendanceRepository;

    @DeleteMapping("/clazz/{clazzId}")
    @Operation(summary = "删除指定班级的所有考勤信息", description = "根据班级ID删除该班级的所有考勤记录")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功删除考勤信息"),
            @ApiResponse(responseCode = "400", description = "请求参数有误，无法删除考勤信息")
    })
    public void removeAttendances(
            @Parameter(description = "班级ID", required = true) @PathVariable Long clazzId) {
        attendanceService.removeAllAttendances(clazzId);
    }



    @GetMapping("/week/{week}/clazz/{clazzId}")
    @Operation(summary = "查看某周课堂考勤信息列表", description = "根据周数和班级ID获取课堂考勤信息列表")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功获取某周课堂考勤信息列表"),
            @ApiResponse(responseCode = "400", description = "请求参数有误，无法获取课堂考勤信息列表")
    })
    public List<ResponseDtoAttendance> getAttendances(
            @Parameter(description = "周数", required = true, example = "1") @PathVariable int week,
            @Parameter(description = "班级ID", required = true, example = "123") @PathVariable Long clazzId) {

        return this.modelFinder.findAllByWeekAndClazzId(week, clazzId).stream()
                .map(t -> new ResponseDtoAttendance(t))
                .collect(Collectors.toList());
    }

    /**
     * 获取指定ID的考勤记录及其详细信息，包括课程安排和其下的班级信息。
     * 
     * @param id 考勤记录ID
     * @return 包含课程安排和班级信息的考勤记录
     */
    @GetMapping("/{id}/details")
    @Operation(summary = "获取考勤记录详细信息", description = "获取指定ID的考勤记录及其课程安排信息，以及与课程安排连带的班级信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功获取考勤记录详细信息"),
            @ApiResponse(responseCode = "404", description = "未找到对应的考勤记录")
    })
    public ResponseDtoAttendanceWithDetails getAttendanceWithCourseScheduleAndClazz(
            @Parameter(description = "考勤记录ID", required = true, example = "456") @PathVariable long id) {
        Attendance attendance = this.modelFinder.getAttendanceWithScheduleClazzAndDetailsById(id);
        if (attendance == null) {
            throw new RuntimeException("考勤记录未找到");
        }
        return new ResponseDtoAttendanceWithDetails(attendance);
    }


    @PostMapping("/start/{courseScheduleId}")
    @Operation(summary = "开始考勤", description = "根据课程安排ID开始考勤")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功开始考勤"),
            @ApiResponse(responseCode = "400", description = "请求参数有误，无法开始考勤"),
            @ApiResponse(responseCode = "401", description = "未登录")
    })
    public void startAttendance(@PathVariable Long courseScheduleId) {
        // 移除以下登录验证代码
        // Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // String username = authentication.getName();
        // if (username == null) {
        //     throw new RuntimeException("未登录");
        // }

        Long id = this.attendanceService.startAttendance(courseScheduleId);
    }

    @PostMapping("/check/{attendId}/{studentId}")
    @Operation(summary = "学生签到", description = "学生根据考勤记录ID和学生ID进行签到")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功签到"),
            @ApiResponse(responseCode = "400", description = "请求参数有误，无法签到"),
            @ApiResponse(responseCode = "401", description = "未登录")
    })
    public void checkAttendance(
            @Parameter(description = "考勤记录ID", required = true, example = "456") @PathVariable Long attendId,
            @Parameter(description = "学生ID", required = true, example = "789") @PathVariable Long studentId) {
      /*  Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        if (!username.equals(studentId) ) {
            throw new RuntimeException("未登录");
        }else{
        */
        this.attendanceService.checkAttendance(attendId,studentId);
       // }

    }


    @PostMapping("/lock/{attendId}/{studentId}")
    @Operation(summary = "锁定考勤", description = "锁定考勤记录，防止进一步修改")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功锁定考勤"),
            @ApiResponse(responseCode = "400", description = "请求参数有误，无法锁定考勤"),
            @ApiResponse(responseCode = "401", description = "未登录")
    })
    public void lockAttendance(
            @Parameter(description = "考勤记录ID", required = true, example = "456") @PathVariable Long attendId,
            @Parameter(description = "学生ID", required = true, example = "789") @PathVariable Long studentId) {
        /*Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        if (!username.equals(studentId) ) {
            throw new RuntimeException("未登录");
        }else{*/
            this.attendanceService.lockAttendance(attendId,studentId);
        //}
    }

    @PostMapping("/submit/{attendId}/{studentId}")
    @Operation(summary = "提交考勤", description = "提交考勤记录，完成考勤流程")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功提交考勤"),
            @ApiResponse(responseCode = "400", description = "请求参数有误，无法提交考勤"),
            @ApiResponse(responseCode = "401", description = "未登录")
    })
    public void submitAttendance(
            @Parameter(description = "考勤记录ID", required = true, example = "456") @PathVariable Long attendId,
            @Parameter(description = "学生ID", required = true, example = "789") @PathVariable Long studentId) {

            this.attendanceService.submitAttendance(attendId,studentId);

    }

    @PostMapping("/tune/{attendId}/{studentId}")
    @Operation(summary = "调整考勤记录", description = "在锁定后调整考勤记录")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功保存考勤记录"),
            @ApiResponse(responseCode = "400", description = "请求参数有误，无法保存考勤记录")
    })
    public long tuneAttendance(
            @Parameter(description = "考勤表ID", required = true, example = "123") @PathVariable Long attendId,
            @Parameter(description = "考勤员ID", required = true, example = "789") @PathVariable Long studentId,
            @Parameter(description = "考勤记录对象，课程安排属性只需要ID", required = true, example = "123") @RequestBody List<RequestDtoTuneAttendanceItem> requestVO) {


        Map<Student, AttendDetailStatus> studentStatusMap = requestVO.stream().collect(Collectors.toMap(entry -> this.studentRepository.findById(entry.getStudentId())
                        .orElseThrow(() -> new IllegalArgumentException("Student数据不存在！")),
                    entry -> AttendDetailStatus.valueOf(entry.getStatus()))

        );

        long id = this.attendanceService.tuneAttendance(attendId, studentStatusMap);
        return id;
    }

    /**
     * 查询某个学生在某个考勤表上的出勤情况
     * @param studentId 学生ID
     * @return 学生出勤状态映射表
     */
    @GetMapping("detailstatus/{studentId}")
    @Operation(summary = "查询学生出勤状态", description = "根据学生ID查询该学生在所有考勤表中的出勤状态")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功获取学生出勤状态"),
        @ApiResponse(responseCode = "400", description = "请求参数有误，无法获取学生出勤状态"),
        @ApiResponse(responseCode = "404", description = "未找到对应学生")
    })
    public Map<Long, String> getAttendancesDetailStatusOfGivenStudent(
        @Parameter(description = "学生ID", required = true, example = "789") @PathVariable Long studentId) {
        Map<Long, AttendDetailStatus> attendDetailStatusMap = this.modelFinder.getAttendancesDetailStatusOfGivenStudent(studentId);
        return attendDetailStatusMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
                entry -> entry.getValue().name()));
    }


}
